package com.tengju.bff.interfaces.covercharge.controller.admin;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.idanchuang.component.config.apollo.util.ConfigUtil;
import com.idanchuang.component.redis.util.DRedisLocks;
import com.idanchuang.component.redis.util.RedisUtil;
import com.tengju.bff.interfaces.covercharge.constant.*;
import com.tengju.bff.interfaces.covercharge.entity.dto.CycleAddInfo;
import com.tengju.bff.interfaces.covercharge.entity.po.ServiceLetaxWithdrawLog;
import com.tengju.bff.interfaces.covercharge.entity.po.ServiceWithdrawFlow;
import com.tengju.bff.interfaces.covercharge.entity.vo.*;
import com.tengju.bff.interfaces.covercharge.service.IServiceLetaxWithdrawLogService;
import com.tengju.bff.interfaces.covercharge.service.IServiceWithdarwCycleAddService;
import com.tengju.bff.interfaces.covercharge.service.IServiceWithdrawFlowService;
import com.tengju.bff.interfaces.covercharge.util.DateTimeUtils;
import com.tengju.bff.interfaces.covercharge.util.ExcelReadUtil;
import com.tengju.bff.interfaces.covercharge.util.alarmUtil.MsgSendUtil;
import com.tengju.bff.interfaces.shared.ApiResponse;
import com.tengju.bff.interfaces.shared.export.PersonalGiveExportQuery;
import com.tengju.bff.interfaces.shared.servlet.ManageEntrance;
import com.tengju.bff.interfaces.shared.servlet.ManageUtil;
import com.tengju.bff.interfaces.shared.servlet.ServletContextUtil;
import com.tengju.export.application.ExportService;
import com.tengju.export.domain.record.ExportDataType;
import com.tengju.export.domain.record.ExportFileType;
import com.tengju.settlement.domain.model.account.UserIdCode;
import com.tengju.settlement.domain.model.depository.DepositoryAccountRepository;
import com.tengju.user.application.user.UserDataAuthService;
import com.tengju.user.domain.model.user.Staff;
import com.tengju.user.domain.model.user.StaffId;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@RestController
@Slf4j
@RequestMapping("/manage/personalGive")
@Api(value = "personalGive", tags = "个体发放管理")
@ManageEntrance
public class PersonalGiveController {
    //线程最大处理数
    private final static Integer SPLIT_MAX_NUM = 1000;

    //每页数量
    private final static Integer PAGE_SIZE = 10000;

    //缓存存在时间，6个小时，转化为毫秒
    private final static Integer REDIS_KEY_TIME = 21600000;

    @Autowired
    private IServiceLetaxWithdrawLogService serviceLetaxWithdrawLogService;

    @Autowired
    private IServiceWithdrawFlowService withdrawFlowService;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private IServiceWithdarwCycleAddService serviceWithdarwCycleAddService;

    @Resource
    private UserDataAuthService userDataAuthService;
    @Autowired
    private ExportService exportService;

    @Autowired
    private DepositoryAccountRepository depositoryAccountRepository;

    private final ForkJoinPool forkJoinPool = (ForkJoinPool) Executors.newWorkStealingPool(5);

    @GetMapping("/list")
    @ResponseBody
    @RequiresRoles("sso")
    @ApiOperation(value = "查询个体发放列表")
    public ApiResponse<Page<PersonalGiveVo>> list(PersonalGiveQuery personalGiveQuery, @RequestParam String appCode,
                                                  @RequestParam Long ssoUserId) {
        Integer pageNo = personalGiveQuery.getPageNo();
        Integer limit = personalGiveQuery.getLimit();
        Page<PersonalGiveVo> result = serviceLetaxWithdrawLogService.queryPersonalGiveList(new Page<>(pageNo, limit), personalGiveQuery);
        Staff staff = ManageUtil.getOperateUser();
        log.info("[支付后台][查询个体发放列表][查看用户:{}]", staff.getStaffId().getValue());
        result.setRecords(userDataAuthService.dataMasking(result.getRecords(), staff.getStaffId()));
        return ApiResponse.newSuccess(result);
    }

    @GetMapping("/moneyTotal")
    @ResponseBody
    @RequiresRoles("sso")
    @ApiOperation(value = "查询统计金额")
    public ApiResponse<PersonalGiveMoneyTotalVo> moneyTotal(PersonalGiveQuery personalGiveQuery) {
        PersonalGiveMoneyTotalVo result = serviceLetaxWithdrawLogService.queryPersonalGiveMoneyTotal(personalGiveQuery);
        return ApiResponse.newSuccess(result);
    }

    @RequestMapping(value = "/export", method = RequestMethod.GET)
    @ApiOperation(value = "导出个体发放列表")
    public ApiResponse<Object> export(PersonalGiveQuery personalGiveQuery) {
        StaffId staffId = ServletContextUtil.getServletContext().getStaffId();
        String realName = ServletContextUtil.getServletContext().getRealName();

        PersonalGiveExportQuery exportQuery = new PersonalGiveExportQuery();
        exportQuery.setPageNo(1);
        exportQuery.setLimit(10000);
        exportQuery.setCycleDate(personalGiveQuery.getCycleDate());
        exportQuery.setAuthType(personalGiveQuery.getAuthType());
        exportQuery.setStatus(personalGiveQuery.getStatus());
        exportQuery.setLetaxStatus(personalGiveQuery.getLetaxStatus());
        exportQuery.setStaffId(staffId);

        exportService.exportData("个人收益打款_" + personalGiveQuery.getCycleDate() + "_" + personalGiveQuery.getAuthType(),
                ExportFileType.XLSX,
                "personalGiveExportDataSourceRepository",
                ExportDataType.TABLE, exportQuery,
                staffId.getValue(), realName);
        return ApiResponse.newSuccess();
    }

    @GetMapping("/giveList")
    @ResponseBody
    @ApiOperation(value = "查询打款记录")
    @RequiresRoles("sso")
    public ApiResponse<List<WithdrawFlow>> giveList(PersonalGiveQuery personalGiveQuery) {
        ServiceWithdrawFlow withdrawFlowParam = new ServiceWithdrawFlow();
        withdrawFlowParam.setIdCode(personalGiveQuery.getIdCode());
        withdrawFlowParam.setPlatformCode(personalGiveQuery.getPlatformCode());
        withdrawFlowParam.setCycleAddId(personalGiveQuery.getCycleAddId());

        List<ServiceWithdrawFlow> list = withdrawFlowService.list(new QueryWrapper<>(withdrawFlowParam));
        List<WithdrawFlow> resultList = new ArrayList<>();
        for (ServiceWithdrawFlow serviceWithdrawFlow : list) {
            WithdrawFlow withdrawFlow = new WithdrawFlow();
            withdrawFlow.setChannel(serviceWithdrawFlow.getChannel());
            withdrawFlow.setId(serviceWithdrawFlow.getId());
            withdrawFlow.setIdcardName(serviceWithdrawFlow.getIdcardName());
            withdrawFlow.setIdCode(serviceWithdrawFlow.getIdCode());
            withdrawFlow.setPlatformCode(serviceWithdrawFlow.getPlatformCode());
            withdrawFlow.setRemark(serviceWithdrawFlow.getRemark());
            withdrawFlow.setStatus(serviceWithdrawFlow.getStatus());
            if (CoverChargeEnum.CommonStatus.YES.getCode().equals(serviceWithdrawFlow.getStatus())) {
                withdrawFlow.setStatusStr("打款成功");
            } else if (CoverChargeEnum.CommonStatus.NO.getCode().equals(serviceWithdrawFlow.getStatus())) {
                withdrawFlow.setStatusStr("打款失败");
            }
            withdrawFlow.setWithdrawer(serviceWithdrawFlow.getWithdrawer());
            withdrawFlow.setWithdrawTime(serviceWithdrawFlow.getWithdrawTime());
            resultList.add(withdrawFlow);
        }
        return ApiResponse.newSuccess(resultList);
    }

    @PostMapping("/updateWithdrawFlowRemark")
    @ResponseBody
    @ApiOperation(value = "更新打款流水备注")
    public ApiResponse<String> updateWithdrawFlowRemark(@RequestBody WithdrawFlow withdrawFlow) {
        Assert.notNull(withdrawFlow.getId(), "打款流水ID不能为空");
        Assert.hasText(withdrawFlow.getRemark(), "打款备注不能为空");

        serviceLetaxWithdrawLogService.updateWithdrawRemark(withdrawFlow.getId(), withdrawFlow.getRemark());
        return ApiResponse.newSuccess();
    }

    @PostMapping("/importGive")
    @ResponseBody
    @ApiOperation(value = "导入打款状态")
    @RequiresRoles("sso")
    public ApiResponse<String> importGive(@RequestBody PersonalGiveImport personalGiveImport) {
        Assert.hasText(personalGiveImport.getChannel(), "打款渠道不能为空");
        Assert.hasText(personalGiveImport.getCycleDate(), "提现周期不能为空");
        Assert.hasText(personalGiveImport.getPlatformCode(), "平台编号不能为空");
        Assert.hasText(personalGiveImport.getCreator(), "打款人不能为空");

        String flag = personalGiveImport.getChannel() + "_" + personalGiveImport.getCycleDate() + "_" + personalGiveImport.getPlatformCode();

        String url = personalGiveImport.getUrl();
        Assert.hasText(url, "上传url不能为空");

        HttpClient client = new HttpClient();
        client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");// 指定传送字符集为UTF-8格式
        client.getHttpConnectionManager().getParams().setConnectionTimeout(10000);// 设置连接超时时间为10秒（连接初始化时间）
        GetMethod method = new GetMethod(url);

        List<String[]> allExcelInfo = null;
        try {
            int statusCode = client.executeMethod(method);
            Assert.isTrue(statusCode == HttpStatus.SC_OK, "statusCode:" + statusCode);
            log.debug(url + ",statusCode:" + statusCode);
            allExcelInfo = ExcelReadUtil.getAllExcelInfo(method.getResponseBodyAsStream(), !url.contains("xlsx"), null, null, "0", "100000", 0);
        } catch (Exception e) {
            log.error("读取excel失败", e);
            Assert.isTrue(false, e.getMessage());
        } finally {
            client.getHttpConnectionManager().closeIdleConnections(1);
        }

        Assert.notEmpty(allExcelInfo, "没有读取到excel内容，请检查");

        List<String[]> finalAllExcelInfo = allExcelInfo;
        return DRedisLocks.runWithLock(BizConstants.WITHDRAWAL_STATUS_IMPORT + flag, 10000, () -> {
            try {
                PersonalGiveImportTaskResult taskResult = serviceLetaxWithdrawLogService.importPersonalGiveCreateTask(finalAllExcelInfo.size() - 1, personalGiveImport);
                if (taskResult.isTaskResult()) {
                    threadPoolExecutor.execute(() -> {
                        try {
                            serviceLetaxWithdrawLogService.importPersonalGive(taskResult.getTaskNo(), finalAllExcelInfo, personalGiveImport);
                        } catch (Exception e) {
                            log.error("异步线程-导入打款数据处理异常:", e);
                        }
                    });
                    return ApiResponse.newSuccess("任务编号：" + taskResult.getTaskNo() + ",任务标识：" + taskResult.getTaskKey());
                }
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), taskResult.getErrorMsg());
            } catch (Exception e) {
                log.error("importGive error", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });

    }

    @PostMapping("/updateStatus")
    @ResponseBody
    @ApiOperation(value = "更新打款状态")
    public ApiResponse<String> updateStatus(@RequestBody PersonalGiveVo personalGiveVo) {
        if (personalGiveVo.getStatus() == null) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "发放状态不能为空");
        }
        if (personalGiveVo.getIdCode() == null) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "打款人不能为空");
        }
        Assert.hasText(personalGiveVo.getBankNo(), "银行卡号不能为空");
        Assert.hasText(personalGiveVo.getChannel(), "打款渠道不能为空");
        Assert.hasText(personalGiveVo.getCycleDate(), "提现周期不能为空");
        Assert.hasText(personalGiveVo.getPlatformCode(), "平台编号不能为空");
        Assert.hasText(personalGiveVo.getOperator(), "打款人不能为空");
        String flag = personalGiveVo.getChannel() + "_" + personalGiveVo.getCycleDate() + "_" + personalGiveVo.getPlatformCode();
        return DRedisLocks.runWithLock(BizConstants.WITHDRAWAL_STATUS_IMPORT + flag, 10000, () -> {
            try {
                serviceLetaxWithdrawLogService.updatePersonalGive(personalGiveVo);
            } catch (Exception e) {
                log.error("[服务费管理后台][单笔更新打款状态]-失败,有异常抛出,idCode:{},错误信息：{}", personalGiveVo.getIdCode(), e.getMessage());
                return ApiResponse.newFailure(CoverChargeErrorCode.BUSINESS_ERROR.getCode(), e.getMessage());
            }
            return ApiResponse.newSuccess();
        });
    }

    @PostMapping("/updateStatusLeTax")
    @ResponseBody
    @ApiOperation(value = "乐税代发更新打款状态")
    public ApiResponse<String> updateStatusLeTax(@RequestBody PersonalGiveVo personalGiveVo) {
        if (StringUtils.isBlank(personalGiveVo.getAuthType())) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "认证类型不能为空");
        }

        //个人
        if (SignIdentityEnum.person.getDesc().equals(personalGiveVo.getAuthType())) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "打款类型不对");
        }

        //注册个体户
        if (SignIdentityEnum.regist_soho.getDesc().equals(personalGiveVo.getAuthType()) && personalGiveVo.getCycleAddId() == null) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "提现记录不能为空");
        }

        Assert.hasText(personalGiveVo.getBankNo(), "银行卡号不能为空");
        Assert.hasText(personalGiveVo.getCycleDate(), "提现周期不能为空");
        Assert.hasText(personalGiveVo.getPlatformCode(), "平台编号不能为空");
        Assert.hasText(personalGiveVo.getOperator(), "打款人不能为空");
        return DRedisLocks.runWithLock(BizConstants.NOT_INVOICE_ONLINE_PAY_MONEY + personalGiveVo.getCycleAddId(), 1000, () -> {
            try {
                DealSinglePayResult dealSinglePayResult = serviceLetaxWithdrawLogService.updateStatusLeTax(personalGiveVo);
                if (!dealSinglePayResult.isPayResult()) {
                    return ApiResponse.newFailure(CoverChargeErrorCode.BUSINESS_ERROR.getCode(), dealSinglePayResult.getErrorMsg());
                }
            } catch (Exception e) {
                log.error("[服务费管理后台][单笔更新打款状态]-失败,有异常抛出,cycleAddId:{},错误信息：{}", personalGiveVo.getCycleAddId(), e.getMessage());
                return ApiResponse.newFailure(CoverChargeErrorCode.BUSINESS_ERROR.getCode(), e.getMessage());
            }
            return ApiResponse.newSuccess();
        });
    }

    @RequiresRoles("sso")
    @PostMapping("/batchOnlinePayMoney")
    @ResponseBody
    @ApiOperation(value = "注册个体户,个人提现申请批量/单个打款", notes = "注册个体户提现申请批量/单个打款")
    public ApiResponse<?> batchOnlinePayMoney(@RequestBody AdminPersonalGiveOnlinePayQueryVo req) {
        List<Integer> cycleAddIdList = req.getCycleAddIds();
        if (CollectionUtils.isEmpty(cycleAddIdList)) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "请选择需要打款的周期记录！");
        }
        String approvers = req.getApprovers();
        Assert.hasText(approvers, "打款人不能为空");

        return DRedisLocks.runWithLock(BizConstants.NOT_INVOICE_ONLINE_PAY_MONEY + req.getCycleAddIds(), 1000, () -> {
            try {
                //错误返回定义
                List<String> responseMsg = Lists.newArrayList();
                for (Integer cycleAddId : cycleAddIdList) {

                    //获取key
                    String lockKey = BizConstants.SERVICE_WITHDRAW_CYCLE_ADD_ONLINE_PAY_MONEY + cycleAddId;
                    Integer cycleId = RedisUtil.getInstance().getObj(lockKey);
                    if (Objects.nonNull(cycleId)) {
                        responseMsg.add("序号为" + cycleAddId + "的周期记录" + "正在处理中");
                        continue;
                    }
                    //存入key
                    if (!RedisUtil.getInstance().setObjIfAbsent(lockKey, cycleAddId)) {
                        responseMsg.add("序号为" + cycleAddId + "的周期记录" + "缓存失败");
                        continue;
                    }

                    PayMoneyResult payMoneyResult = serviceWithdarwCycleAddService.onlinePayMoneyCheck(cycleAddId);
                    if (!payMoneyResult.isPayResult()) {
                        responseMsg.add(payMoneyResult.getErrorMsg());
                        //失败释放缓存
                        serviceWithdarwCycleAddService.delRedisKey(cycleAddId);
                    } else {
                        //生成交易单
                        serviceWithdarwCycleAddService.createCycleAddTransOrder(cycleAddId, approvers);
                        //获取传输参数
                        CycleAddInfo cycleAddInfo = serviceWithdarwCycleAddService.getCycleAddInfo(cycleAddId, approvers);
                        //mq处理
//                        serviceWithdarwCycleAddService.(cycleAddInfo);
                        serviceWithdarwCycleAddService.dealOnlinePayMoney(cycleAddInfo);
                    }

                }
                return ApiResponse.newSuccess(responseMsg);
            } catch (Exception e) {
                log.error("[服务费后台][个人收益打款申请记录][批量打款失败,有异常抛出]", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), "批量打款失败");
            }
        });
    }

    @PostMapping("/allOnlinePayMoney")
    @ResponseBody
    @ApiOperation(value = "注册个体户,个人提现申请全量打款", notes = "注册个体户提现申请全量打款")
    public ApiResponse<?> allOnlinePayMoney(@RequestBody AdminPersonalGiveOnlinePayQueryVo req) {
        //判断是否传入周期时间(此条件为必要条件)
        String date = req.getDate();
        if (StringUtils.isBlank(date)) {
            log.info("[服务费后台][注册个体户提现申请记录][全量打款失败,周期时间为空]");
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "请选择周期时间！");
        }
        String approvers = req.getApprovers();
        Assert.hasText(approvers, "打款人不能为空");

        //获取周期开始和结束时间
        String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
        String startDateStr = DateTimeUtils.parseDateAsString(
                DateTimeUtils.addMonths(DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT), -1),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";

        String endDateStr = DateTimeUtils.parseDateAsString(
                DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + cycleDay + " 23:59:59";

        //基本的业务校验
        PayMoneyResult payMoneyResult = serviceWithdarwCycleAddService.onlineFullPayMoneyCheck(startDateStr, endDateStr);
        if (!payMoneyResult.isPayResult()) {
            return ApiResponse.newFailure(CoverChargeErrorCode.BUSINESS_ERROR.getCode(), payMoneyResult.getErrorMsg());
        }

        return DRedisLocks.runWithLock(BizConstants.NOT_INVOICE_ONLINE_PAY_MONEY + date, 1000, () -> {
            try {
                //参数拼接
                PersonalGiveQuery personalGiveQuery = new PersonalGiveQuery();
                personalGiveQuery.setAuthType(SignIdentityEnum.regist_soho.getCode());
                personalGiveQuery.setCycleDate(req.getDate());
                personalGiveQuery.setStartDate(startDateStr);
                personalGiveQuery.setEndDate(endDateStr);
                //查询符合条件的周期记录总数
                Page<PersonalGiveVo> pageResultTotal = serviceLetaxWithdrawLogService.queryPersonalGiveAllListAllPaid(new Page<>(1, 1), personalGiveQuery);

                //获取总数
                long count = pageResultTotal.getTotal();

                log.info("[服务费后台][全量打款总数]，count={}", count);

                //获取页数
                int page = Math.toIntExact((count / PAGE_SIZE + (count % PAGE_SIZE > 0 ? 1 : 0)));

                log.info("[服务费后台][全量打款总页数]，page={}", page);

                List<String> responseMsg = Lists.newArrayList();

                Page<PersonalGiveVo> pageResult = serviceLetaxWithdrawLogService.queryPersonalGiveAllListAllPaid(new Page<>(1, 1), personalGiveQuery);
                List<PersonalGiveVo> list = pageResult.getRecords();

                if (CollectionUtils.isEmpty(list)) {
                    return ApiResponse.newFailure(CoverChargeErrorCode.BUSINESS_ERROR.getCode(), "该查询条件下无可打款记录");
                }

                //分页获取符合条件页数
                new Thread(() -> {

                    fullUpdateByPage(page, personalGiveQuery, approvers);

                }).start();


                return ApiResponse.newSuccess(responseMsg);
            } catch (Exception e) {
                log.error("[服务费后台][个人收益打款申请记录][全量打款失败,有异常抛出]", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), "打款失败");
            }
        });
    }

    private void fullUpdateByPage(int page, PersonalGiveQuery personalGiveQuery, String approvers) {

        for (int i = 1; i <= page; i++) {
            Page<PersonalGiveVo> pageResult = serviceLetaxWithdrawLogService.queryPersonalGiveAllListAllPaid(new Page<>(i, PAGE_SIZE), personalGiveQuery);
            List<PersonalGiveVo> list = pageResult.getRecords();

            log.info("[服务费后台][全量打款][多线程开始执行]，page={},pageSize={}", i, PAGE_SIZE);
            //多线程全量审核更新
            fullUpdate(list, approvers);

        }

    }


    /**
     * @return PayMoneyResult
     * @Description 多线程全量打款
     * @Author cj
     * @Param [applyList, approvers]
     * @Date: 2020/10/28
     **/
    private List<String> fullUpdate(List<PersonalGiveVo> applyList, String approvers) {
        //错误返回定义
        List<String> responseMsg = Lists.newArrayList();
        List<ForkJoinTask> forkJoinTasks = Lists.newArrayList();
        try {
            //多线程处理
            for (int i = 0; i < applyList.size(); i = i + SPLIT_MAX_NUM) {
                List<PersonalGiveVo> subapplyList = applyList.stream().skip(i).limit(SPLIT_MAX_NUM)
                        .collect(Collectors.toList());
                ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> {
                    for (PersonalGiveVo list : subapplyList) {
                        //获取key
                        String lockKey = BizConstants.SERVICE_WITHDRAW_CYCLE_ADD_ONLINE_PAY_MONEY + list.getCycleAddId();
                        Integer cycleId = RedisUtil.getInstance().getObj(lockKey);
                        if (Objects.nonNull(cycleId)) {
                            MsgSendUtil.sendLarkMsg("序号为" + list.getCycleAddId() + "的周期记录" + "正在处理中");
                            continue;
                        }
                        //存入key
                        if (!RedisUtil.getInstance().setObjIfAbsent(lockKey, list.getCycleAddId())) {
                            MsgSendUtil.sendLarkMsg("序号为" + list.getCycleAddId() + "的周期记录" + "存入缓存失败");
                            continue;
                        }
                        //必要校验
                        PayMoneyResult payMoneyResult = serviceWithdarwCycleAddService.onlineAllPayMoneyCheck(list.getCycleAddId());
                        if (!payMoneyResult.isPayResult()) {
                            MsgSendUtil.sendLarkMsg(payMoneyResult.getErrorMsg());
                            log.warn("[服务费后台][个人收益打款申请记录][全量打款失败,周期校验失败]，cycleAddId={},response={}", list.getCycleAddId(), payMoneyResult.getErrorMsg());
                            //失败释放缓存
                            serviceWithdarwCycleAddService.delRedisKey(list.getCycleAddId());
                            continue;
                        }

                        //生成交易单
                        serviceWithdarwCycleAddService.createCycleAddTransOrder(list.getCycleAddId(), approvers);

                        //获取传输参数
                        CycleAddInfo cycleAddInfo = serviceWithdarwCycleAddService.getCycleAddInfo(list.getCycleAddId(), approvers);
                        //mq处理

                        //serviceWithdarwCycleAddService.sendOnlinePayMoneyMessage(cycleAddInfo);
                        serviceWithdarwCycleAddService.dealOnlinePayMoney(cycleAddInfo);
                    }
                });
                forkJoinTasks.add(forkJoinTask);
            }

            for (ForkJoinTask forkJoinTask : forkJoinTasks) {

                forkJoinTask.get();

            }

        } catch (Exception e) {
            log.error("[服务费后台][个人收益打款申请记录][全量打款失败,多线程执行过程中有异常抛出]", e);
        }
        return responseMsg;
    }

    @PostMapping("/delPayMoneyRedis")
    @ResponseBody
    @ApiOperation(value = "注册个体户/个人提现申请批量删除缓存", notes = "注册个体户/个人提现申请批量删除缓存")
    public ApiResponse<?> delPayMoneyRedis(@RequestBody AdminPersonalGiveOnlinePayQueryVo req) {
        Integer getCycleAddId = req.getCycleAddId();
        if (getCycleAddId == null) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "请选择需要删除的周期记录！");
        }
        //失败释放缓存
        serviceWithdarwCycleAddService.delRedisKey(getCycleAddId);
        //获取key
        String lockKey = BizConstants.SERVICE_WITHDRAW_CYCLE_ADD_ONLINE_PAY_MONEY + getCycleAddId;
        Integer cycleId = RedisUtil.getInstance().getObj(lockKey);
        return ApiResponse.newSuccess(cycleId);
    }

    @PostMapping("/queryPayData")
    @ResponseBody
    @ApiOperation(value = "注册个体户,个人提现打款查询", notes = "个人提现打款查询")
    @RequiresRoles("sso")
    public ApiResponse<?> queryPayData(@RequestBody AdminPersonalGiveOnlinePayQueryVo req) {
        //判断是否传入周期时间(此条件为必要条件)
        String date = req.getDate();
        if (StringUtils.isBlank(date)) {
            log.info("[服务费后台][个人提现打款查询失败][周期时间为空]");
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "请选择周期时间！");
        }

        //获取周期开始和结束时间
        String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
        String startDateStr = DateTimeUtils.parseDateAsString(
                DateTimeUtils.addMonths(DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT), -1),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";

        String endDateStr = DateTimeUtils.parseDateAsString(
                DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + cycleDay + " 23:59:59";

        return DRedisLocks.runWithLock(BizConstants.SERVICE_WITHDRAW_CYCLE_ADD_ONLINE_PAY_QUERY_MONEY + date, 10000, () -> {
            try {
                QueryPayDataResult queryPayDataResult = serviceLetaxWithdrawLogService.getPayData(date, startDateStr, endDateStr);
                return ApiResponse.newSuccess(queryPayDataResult);
            } catch (Exception e) {
                log.error("[服务费后台][个人提现打款查询][有异常抛出]", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), "查询失败");
            }
        });
    }
}
